#pragma
#include<iostream>
#include<sys/select.h>
#include<sys/time.h>
 #include"Log.hpp"
#include"Socket.hpp"
using namespace std;

static const uint16_t defaultport=8080;
const int defaultfd=-1;
static const int fd_num_max=(sizeof(fd_set)*8);

class SelectServer
{
public:
    SelectServer(uint16_t port=defaultport):_port(port)
    {
        for(int i=0;i<fd_num_max;i++)
        {
            fd_arry[i]=defaultfd;
        }
    }
    bool Init()
    {
        _listensock.Socket();
        _listensock.Bind(_port);
        _listensock.Listen();
        return true;

    }
    void Recver(int fd)
    {
        char buffer[1024];

    }
    void HandleEvent(fd_set& rfds)
    {
        if(FD_ISSET(_listensock.Fd(),&rfds))
        {
            //
            string clientip;
            uint16_t clientport=0;
            int sock=_listensock.Accept(&clientip,&clientport);
            if(sock<0)  return ;
            lg(Info,"accept success,%s:%d,sock fd:%d",clientip.c_str(),clientport,sock);

            int pos=1;
            for(;pos<fd_num_max;pos++)
            {
                if(fd_arry[pos]!=defaultfd) continue;
                else break;
            }
            if(pos==fd_num_max)
            {
                lg(Warning,"server is full,close %d now",sock);
                close(sock);
            }
            else {
                fd_arry[pos]=sock;
                PrintFd();
            }

        }
    }
    void Start()
    {
        int listensock=_listensock.Fd();
        fd_arry[0]=listensock;
        for(;;)
        {
            fd_set fds;
            FD_ZERO(&fds);
            int maxfd=fd_arry[0];
            for(int i=0;i<fd_num_max;i++)
            {
                if(fd_arry[i]==defaultfd) continue;
                FD_SET(fd_arry[i],&fds);

                if(maxfd<fd_arry[i])
                {
                    maxfd=fd_arry[i];
                    lg(Info,"max fd update,maxfd is:%d",maxfd);
                }
            }
            //不能直接accept,检测并获取listensock 上面的事件，等价于读事件就绪。
            fd_set rfds;
            FD_ZERO(&rfds);
            FD_SET(listensock,&rfds);
            struct timeval timeout={0,0};
            int n=select(listensock+1,&rfds,nullptr,nullptr,&timeout);
            switch(n)
            {
                case 0:
                    cout<<"time out,timeout: "<<timeout.tv_sec<<"."<<timeout.tv_usec<<endl;
                    break;
                case -1:
                    cout<<"select erro"<<endl;
                default:
                    HandleEvent(rfds);
                    cout<<"get a new Link"<<endl;
                    break;
            }
        }
    
    }
    void PrintFd()
    {
        cout<<"online fd list:";
        for(int i=0;i<fd_num_max;i++)
        {
            if(fd_arry[i]==defaultfd)   continue;
            cout<<fd_arry[i]<<" ";
        }
        cout<<endl;
    }
    ~SelectServer()
    {}
private:
    Sock _listensock;
    uint16_t _port;
    int fd_arry[fd_num_max];
};